<a href='https://github.com/angular/angular.js/edit/v1.5.x/docs/content/tutorial/step_06.ngdoc?message=docs(tutorial%2F6 - Two-way Data Binding)%3A%20describe%20your%20change...' class='improve-docs btn btn-primary'><i class="glyphicon glyphicon-edit">&nbsp;</i>Improve this Doc</a>


<ul doc-tutorial-nav="6"></ul>


<p>In this step, we will add a feature to let our users control the order of the items in the phone
list. The dynamic ordering is implemented by creating a new model property, wiring it together with
the repeater, and letting the data binding magic do the rest of the work.</p>
<ul>
<li>In addition to the search box, the application displays a drop-down menu that allows users to
control the order in which the phones are listed.</li>
</ul>
<div doc-tutorial-reset="6"></div>


<h2 id="component-template">Component Template</h2>
<p><br />
<strong><code>app/phone-list/phone-list.template.html</code>:</strong></p>
<pre><code class="lang-html">&lt;div class=&quot;container-fluid&quot;&gt;
  &lt;div class=&quot;row&quot;&gt;
    &lt;div class=&quot;col-md-2&quot;&gt;
      &lt;!--Sidebar content--&gt;

      &lt;p&gt;
        Search:
        &lt;input ng-model=&quot;$ctrl.query&quot;&gt;
      &lt;/p&gt;

      &lt;p&gt;
        Sort by:
        &lt;select ng-model=&quot;$ctrl.orderProp&quot;&gt;
          &lt;option value=&quot;name&quot;&gt;Alphabetical&lt;/option&gt;
          &lt;option value=&quot;age&quot;&gt;Newest&lt;/option&gt;
        &lt;/select&gt;
      &lt;/p&gt;

    &lt;/div&gt;
    &lt;div class=&quot;col-md-10&quot;&gt;
      &lt;!--Body content--&gt;

      &lt;ul class=&quot;phones&quot;&gt;
        &lt;li ng-repeat=&quot;phone in $ctrl.phones | filter:$ctrl.query | orderBy:$ctrl.orderProp&quot;&gt;
          &lt;span&gt;{{phone.name}}&lt;/span&gt;
          &lt;p&gt;{{phone.snippet}}&lt;/p&gt;
        &lt;/li&gt;
      &lt;/ul&gt;

    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</code></pre>
<p>We made the following changes to the <code>phone-list.template.html</code> template:</p>
<ul>
<li><p>First, we added a <code>&lt;select&gt;</code> element bound to <code>$ctrl.orderProp</code>, so that our users can pick from
the two provided sorting options.</p>
<p><img class="diagram" src="img/tutorial/tutorial_06.png"></p>
</li>
<li><p>We then chained the <code>filter</code> filter with the <a href="api/ng/filter/orderBy">orderBy</a> filter to further process the
input for the repeater. <code>orderBy</code> is a filter that takes an input array, copies it and reorders
the copy which is then returned.</p>
<p>Angular creates a two way data-binding between the select element and the <code>$ctrl.orderProp</code> model.
<code>$ctrl.orderProp</code> is then used as the input for the <code>orderBy</code> filter.</p>
</li>
</ul>
<p>As we discussed in the section about data-binding and the repeater in <a href="tutorial/step_05">step 5</a>,
whenever the model changes (for example because a user changes the order with the select drop-down
menu), Angular&#39;s data-binding will cause the view to automatically update. No bloated DOM
manipulation code is necessary!</p>
<h2 id="component-controller">Component Controller</h2>
<p><br />
<strong><code>app/phone-list/phone-list.components.js</code>:</strong></p>
<pre><code class="lang-js">angular.
  module(&#39;phoneList&#39;).
  component(&#39;phoneList&#39;, {
    templateUrl: &#39;phone-list/phone-list.template.html&#39;,
    controller: function PhoneListController() {
      this.phones = [
        {
          name: &#39;Nexus S&#39;,
          snippet: &#39;Fast just got faster with Nexus S.&#39;,
          age: 1
        }, {
          name: &#39;Motorola XOOM™ with Wi-Fi&#39;,
          snippet: &#39;The Next, Next Generation tablet.&#39;,
          age: 2
        }, {
          name: &#39;MOTOROLA XOOM™&#39;,
          snippet: &#39;The Next, Next Generation tablet.&#39;,
          age: 3
        }
      ];

      this.orderProp = &#39;age&#39;;
    }
  });
</code></pre>
<ul>
<li><p>We modified the <code>phones</code> model - the array of phones - and added an <code>age</code> property to each phone
record. This property is used to order the phones by age.</p>
</li>
<li><p>We added a line to the controller that sets the default value of <code>orderProp</code> to <code>age</code>. If we had
not set a default value here, the <code>orderBy</code> filter would remain uninitialized until the user
picked an option from the drop-down menu.</p>
</li>
</ul>
<p>This is a good time to talk about two-way data-binding. Notice that when the application is loaded
in the browser, &quot;Newest&quot; is selected in the drop-down menu. This is because we set <code>orderProp</code> to
<code>&#39;age&#39;</code> in the controller. So the binding works in the direction from our model to the UI. Now if
you select &quot;Alphabetically&quot; in the drop-down menu, the model will be updated as well and the phones
will be reordered. That is the data-binding doing its job in the opposite direction — from the UI to
the model.</p>
<h1 id="testing">Testing</h1>
<p>The changes we made should be verified with both a unit test and an E2E test. Let&#39;s look at the unit
test first.</p>
<p><br />
<strong><code>app/phone-list/phone-list.component.spec.js</code>:</strong></p>
<pre><code class="lang-js">describe(&#39;phoneList&#39;, function() {

  // Load the module that contains the `phoneList` component before each test
  beforeEach(module(&#39;phoneList&#39;));

  // Test the controller
  describe(&#39;PhoneListController&#39;, function() {
    var ctrl;

    beforeEach(inject(function($componentController) {
      ctrl = $componentController(&#39;phoneList&#39;);
    }));

    it(&#39;should create a `phones` model with 3 phones&#39;, function() {
      expect(ctrl.phones.length).toBe(3);
    });

    it(&#39;should set a default value for the `orderProp` model&#39;, function() {
      expect(ctrl.orderProp).toBe(&#39;age&#39;);
    });

  });

});
</code></pre>
<p>The unit test now verifies that the default ordering property is set.</p>
<p>We used Jasmine&#39;s API to extract the controller construction into a <code>beforeEach</code> block, which is
shared by all tests in the parent <code>describe</code> block.</p>
<p>You should now see the following output in the Karma tab:</p>
<pre><code>Chrome 49.0: Executed 2 of 2 SUCCESS (0.136 secs / 0.08 secs)
</code></pre>
<p>Let&#39;s turn our attention to the E2E tests.</p>
<p><br />
<strong><code>e2e-tests/scenarios.js</code>:</strong></p>
<pre><code class="lang-js">describe(&#39;PhoneCat Application&#39;, function() {

  describe(&#39;phoneList&#39;, function() {

    ...

    it(&#39;should be possible to control phone order via the drop-down menu&#39;, function() {
      var queryField = element(by.model(&#39;$ctrl.query&#39;));
      var orderSelect = element(by.model(&#39;$ctrl.orderProp&#39;));
      var nameOption = orderSelect.element(by.css(&#39;option[value=&quot;name&quot;]&#39;));
      var phoneNameColumn = element.all(by.repeater(&#39;phone in $ctrl.phones&#39;).column(&#39;phone.name&#39;));

      function getNames() {
        return phoneNameColumn.map(function(elem) {
          return elem.getText();
        });
      }

      queryField.sendKeys(&#39;tablet&#39;);   // Let&#39;s narrow the dataset to make the assertions shorter

      expect(getNames()).toEqual([
        &#39;Motorola XOOM\u2122 with Wi-Fi&#39;,
        &#39;MOTOROLA XOOM\u2122&#39;
      ]);

      nameOption.click();

      expect(getNames()).toEqual([
        &#39;MOTOROLA XOOM\u2122&#39;,
        &#39;Motorola XOOM\u2122 with Wi-Fi&#39;
      ]);
    });

    ...
</code></pre>
<p>The E2E test verifies that the ordering mechanism of the select box is working correctly.</p>
<p>You can now rerun <code>npm run protractor</code> to see the tests run.</p>
<h1 id="experiments">Experiments</h1>
<div></div>

<ul>
<li><p>In the <code>phoneList</code> component&#39;s controller, remove the statement that sets the <code>orderProp</code> value
and you&#39;ll see that Angular will temporarily add a new blank (&quot;unknown&quot;) option to the drop-down
list and the ordering will default to unordered/natural order.</p>
</li>
<li><p>Add a <code>{{$ctrl.orderProp}}</code> binding into the <code>phone-list.template.html</code> template to display its
current value as text.</p>
</li>
<li><p>Reverse the sort order by adding a <code>-</code> symbol before the sorting value:
<code>&lt;option value=&quot;-age&quot;&gt;Oldest&lt;/option&gt;</code></p>
</li>
</ul>
<h1 id="summary">Summary</h1>
<p>Now that you have added list sorting and tested the application, go to <a href="tutorial/step_07">step 7</a> to
learn about Angular services and how Angular uses dependency injection.</p>
<ul doc-tutorial-nav="6"></ul>


